package com.unitd.modules.sys.service.impl;

import com.unitd.comm.constant.ToolConstant;
import com.unitd.frame.comm.tree.Ztree;
import com.unitd.frame.comm.utils.DateUtils;
import com.unitd.frame.comm.utils.StringUtils;
import com.unitd.frame.mybatis.core.dao.IBaseDao;
import com.unitd.frame.mybatis.core.service.impl.BaseServiceImpl;
import com.unitd.modules.sys.dao.ISysOrgDao;
import com.unitd.modules.sys.entity.SysOrg;
import com.unitd.modules.sys.service.ISysOrgService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @desc 机构信息管理业务逻辑控制接口实现类
 * @filename SysOrgServiceImpl.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2017-04-08
 */
@Service("sysOrgService")
public class SysOrgServiceImpl extends BaseServiceImpl<SysOrg, String> implements ISysOrgService {

	@Autowired
	private ISysOrgDao sysOrgDao;

	/**
	 * @return GenericDao实现类
	 * @desc 定义成抽象方法, 由子类实现, 完成dao的注入
	 */
	@Override
	public IBaseDao<SysOrg, String> getDao() {
		return sysOrgDao;
	}

	/**
	 * @desc 插入之前执行方法, 需要手工调用
	 * @param sysOrg 数据保存对象
	 * @param userId 操作人
	 */
	private void preInsert(SysOrg sysOrg, String userId) {
		sysOrg.setId(sysOrgDao.getPrePrimaryKey()); 						// 生成ID
		sysOrg.setCreateBy(userId);
		sysOrg.setCreateDate(DateUtils.formatDate(new Date(), DateUtils.TIMESTAMP_PATTERN));
	}

	/**
	 * @desc 更新之前执行方法，需要手动调用
	 * @param sysOrg 数据保存对象
	 * @param userId 操作人
	 */
	private void preUpdate(SysOrg sysOrg, String userId){
		sysOrg.setUpdateBy(userId);
		sysOrg.setUpdateDate(DateUtils.formatDate(new Date(), DateUtils.TIMESTAMP_PATTERN));
	}

	/**
	 * @desc 根据主键ID获取对应的详情信息
	 * @param id 主键ID
	 * @return 机构详情
	 */
	@Override
	public SysOrg findBy(String id) {
		SysOrg sysOrg = new SysOrg();
		if (!StringUtils.isZero(id)) {
			sysOrg = sysOrgDao.findBy(id);
		}
		return sysOrg;
	}

	/**
	 * @desc 获取所有有效机构, 并按照层级关系进行重新组合
	 * @return 按照层级关系排列的树
	 */
	@Override
	public List<Ztree> getSysOrgTrees() {
		// 从数据库中取出所有有效的机构
		List<SysOrg> orgs = sysOrgDao.findAllData();
		// 对机构列表按照层级关系进行排序
		return sortOrgs(orgs, "-1");
	}

	/**
	 * @desc 根据选择的机构父ID获取该父机构下的最大sort值并+1
	 * @param parentNo 父机构No
	 * @return 某父机构下的最大排序
	 */
	@Override
	public Integer getMaxSortByPNo(String parentNo) {
		return sysOrgDao.getMaxSortByPNo(parentNo);
	}

	/**
	 * @desc 处理数据保存/更新
	 * @param param 前端传送的需要处理的数据
	 * @return 数据保存/更新结果
	 */
	@Override
	@Transactional(rollbackFor={RuntimeException.class, Exception.class, Throwable.class})
	public Integer doEdit(Map<String, Object> param) {
		Integer result = 0;
		SysOrg sysOrg = (SysOrg) param.get(SysOrg.class.getName());
		String userId = (String) param.get(ToolConstant.USER_TOKEN_ID);

		if (sysOrg != null) {
			if (!StringUtils.isZero(sysOrg.getId())) {
				preUpdate(sysOrg, userId);
				result = sysOrgDao.updateByPrimaryKeySelective(sysOrg);
			} else {
				preInsert(sysOrg, userId);
				result = sysOrgDao.insertSelective(sysOrg);
			}
		}
		return result;
	}

	/**
	 * @desc 根据ID串删除机构(同时还需要删除对应的角色-机构关联信息)
	 * @param ids 需要删除的详情信息ID串,多个ID之间用,分割
	 * @return 删除记录条数
	 */
	@Override
	@Transactional(rollbackFor={RuntimeException.class, Exception.class, Throwable.class})
	public Integer doDelete(String ids) {
		Integer result = 0;

		List<String> idList = StringUtils.toList(ids, ",");
		SysOrg param = new SysOrg(); 								// 删除方法的参数对象
		for(String id : idList) {
			param.setId(id); 										// 设置参数

			// 逻辑删除
			result += sysOrgDao.deleteByDelFlag(param);
		}
		return result;
	}

	/**
	 * @desc 获取进行了递归处理的机构树,同时,在树的最顶层包装一个虚拟机构
	 * @param sysOrgs 所有有效的机构列表
	 * @param pId      上级机构ID
	 * @return 树结果对象
	 */
	private List<Ztree> sortOrgs(List<SysOrg> sysOrgs, String pId) {
		List<Ztree> trees = new ArrayList<>();
		// 如果是顶级机构,先建立一个机构跟节点
		Ztree root = new Ztree();
		root.setId("-1"); 											// 机构ID
		root.setName("顶级机构"); 									// 机构名称
		root.setpId(""); 											// 上级机构
		root.setChildren(recursionOrgs(sysOrgs, pId));
		trees.add(root);

		return trees;
	}

	/**
	 * @desc 递归处理多级机构树,将机构按照树进行分组处理
	 * @param sysOrgs 所有有效的机构列表
	 * @param pNo      上级机构No
	 * @return 树结构对象
	 */
	private List<Ztree> recursionOrgs(List<SysOrg> sysOrgs, String pNo) {
		List<Ztree> result = new ArrayList<>();

		Ztree vo; 														// 子节点对象
		for (SysOrg sysOrg : sysOrgs) {
			vo = new Ztree();
			vo.setId(sysOrg.getOrgNo()); 								// 机构ID
			vo.setName(sysOrg.getOrgName()); 							// 机构名称
			vo.setpId(sysOrg.getParentNo()); 							// 上级机构

			String parentNo = sysOrg.getParentNo(); 					// 获取机构的父id
			if (StringUtils.isNotBlank(parentNo)) {
				if (parentNo.equals(pNo)) {
					vo.setChildren(recursionOrgs(sysOrgs, sysOrg.getOrgNo()));
					result.add(vo);
				}
			}
		}
		return result;
	}
}